#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>

#define NUM 1024
#define SIZE 32
#define SEP " "
//保存完整的命令行字符串
char cmd_line[NUM];
//保存打散之后的命令行字符串
char *g_argv[SIZE];

//写一个环境变量用来测试
char g_myval[64];
//shell 运行原理：通过让子进程执行命令，父进程等待&&解析命令
int main()
{
    extern char**environ;
    //0. 命令行解释器，一定是一个常驻内存的进程，不退出
    while(1)
    {
        //1.打印出提示信息
        printf("[root@localhost myshell]#");
        fflush(stdout);
        memset(cmd_line,'\0',sizeof cmd_line);
        //2.获取用户的键盘输入[输入的是各种指令："ls -a -l"]
        if(fgets(cmd_line,sizeof cmd_line,stdin)==NULL)
        {
            continue;
        }
        cmd_line[strlen(cmd_line)-1] = '\0';
        //printf("echo: %s\n",cmd_line);
        //3.命令行字符串打散
        g_argv[0] = strtok(cmd_line,SEP);
        int index = 1;
        if(strcmp(g_argv[0],"ls")==0)
        {
            g_argv[index++] = "--color=auto";
        }
        if(strcmp(g_argv[0],"ll")==0)
        {
            g_argv[0] = "ls";
            g_argv[index++] = "-l";
            g_argv[index++] = "--color=auto";
        }
        while(g_argv[index++] = strtok(NULL,SEP));
        if(strcmp(g_argv[0],"export") == 0 && g_argv[1] != NULL)
        {
            strcpy(g_myval,g_argv[1]);
            int ret = putenv(g_myval);
            if(ret == 0) printf("%s export success\n",g_argv[1]);
            int i = 0;
            for(i;environ[i];i++)
                printf("%d: %s\n",i,environ[i]);
            continue;
        }
        //第二次，如果还要继续分割原始字符串，直接传NULL
        
        //for(index = 0;g_argv[index];index++)
        //    printf("g_argv[%d]: %s\n",index,g_argv[index]);
        //4.TODO,内置命令，让父进程（shell）自己执行的命令，叫做内置命令，内建命令本质就是shell中的一个函数调用
        if(strcmp(g_argv[0],"cd")==0)
        {
            if(g_argv[1]!=NULL) chdir(g_argv[1]);

            continue;
        }
        //5.fork()
        pid_t id = fork();
        if(id == 0)
        {
            printf("下面功能让子进程进行的\n");
            //execvpe(g_argv[0],g_argv,environ);
            execvp(g_argv[0],g_argv);
            exit(1);
        }

        int status = 0;
        pid_t ret = waitpid(id,&status,0);
        if(ret>0) printf("exit code: %d\n",WEXITSTATUS(status));
    }
    return 0;
}
